

// 建立redux模型
function createStore(reduce, preloadState, enhancer) {
    let currentState = preloadState
    let curentListeners = [];
    // 判断reduce是否为函数
    if (typeof reduce !== "function") {
        throw Error("reduce 必须是一个函数")
    }
    // 判断enhancer是否为空
    if (typeof enhancer !== "undefined") {
        if (typeof enhancer !== "function") {
            throw Error("enhancer 必须是一个函数")
        }
        // 调用enhancer传入state和reduce
        return enhancer(createStore)(reduce, preloadState)
    }
    // 获取状态
    function getState() {
        return currentState
    }
    // 触发action
    function dispatch(action) {
        // 判断action是否为对象
        if (!isPlainObject(action)) throw Error("action 必须是一个对象");
        if (typeof action.type === "undefined") throw Error("action 必须有type属性");
        currentState = reduce(currentState, action)
        for (let i = 0; i < curentListeners.length; i++) {
            let listener = curentListeners[i];
            listener()
        }
    }

    //订阅状态
    function subscribe(listener) {
        curentListeners.push(listener)
    }

    // 返回所有的核心方法
    return {
        getState,
        dispatch,
        subscribe,
    }
}

// 判断是否为对象
function isPlainObject(obj) {
    // 非对象或为空直接返回false
    if (typeof obj !== "object" || obj === null) return false
    // 区分数组和对象
    let proto = obj
    // 循环查找上一级直到没有为止
    while (Object.getPrototypeOf(proto) !== null) {
        proto = Object.getPrototypeOf(proto)
    }
    // 如果最后一级跟第一级相等,则为对象
    return proto === Object.getPrototypeOf(obj)

}

// 处理中间件
function applymiddleware(...middlewares) {
    return function (createStore) {
        return function (reduce, preloadState) {
            // 创建Store
            const store = createStore(reduce, preloadState)
            // 用于中间件处理的store
            const StoreAPI = {
                dispatch: store.dispatch,
                getState: store.getState,
            }
            const chain = middlewares.map(middleware => middleware(StoreAPI))
            let dispatch = compose(...chain)(store.dispatch)
            return {
                ...store,
                dispatch: dispatch
            }
        }
    }
}

// 处理中间件的函数嵌套
function compose() {
    var funcs = [...arguments];
    return function (dispatch) {
        // 反推loger(也就是上一层中间件)的next参数,其实就是最后一层thunk的最后一层函数
        for (var i = funcs.length - 1; i >= 0; i--) {
            dispatch = funcs[i](dispatch)
        }
        return dispatch;
    }
}

// bindActionCreatetors函数实现
function bindActionCreatetors(ActionCretors, dispatch) {
    let bindActionCreatetorsobj = {};
    for (let i in ActionCretors) {
        bindActionCreatetorsobj[i] = () => {
            dispatch(ActionCretors[i]())
        }
    }
    return bindActionCreatetorsobj;
}

// 组合小的reduce成一个大的reduce
function combineReducers(reducers) {
    // 判断每一个reduces的类型必须为函数
    let reducerKeys = Object.keys(reducers)
    for (let i = 0; i <= reducerKeys.length - 1; i++) {
        let key = reducerKeys[i]
        if (typeof reducers[key] !== "function") throw Error("reduce必须是一个函数")
    }

    return function (state, action) {
        var nextState = {};
        for (var i = 0; i < reducerKeys.length; i++) {
            var key = reducerKeys[i];
            var reducer = reducers[key];
            var previousStateForKey = state[key];
            nextState[key] = reducer(previousStateForKey, action)
        }
        return nextState;
    }
}